###############################################################################
# Settings

# Project name
PROJECT = "gc"

# Include path
INC_PATHS = %w(include)

# Source files
SRCS = FileList["src/*.c"]

# Project's target
Targets = %w(release debug profile)

####

# Compile option
C_OPT_DBG = "-g -O0 -D_DEBUG"
C_OPT_REL = "-O3 -DNDEBUG"
C_OPT_PRF = "-O3 -DNDEBUG -pg"

OBJ_PATH_BASE = "obj"
OBJ_EXT = ".o"
LIB_PATH = "lib"

CC = "gcc"

AR_OPT = ""
AR = "ar r"

INCLUDES = INC_PATHS.map {|x| "-I#{x}"}.join(" ")


###############################################################################

task :default => Targets[0]
Targets.each_with_index do |name, i|
	task "set-#{name}" do set_target(name); end

	defo = (i == 0) ? " (default)" : ""
	desc "Build #{name} library#{defo}"
	task name => ["set-#{name}", "build"]

	task "clean-#{name}" do set_target(name); clean_target; end
end

desc "Clean target"
task "clean" => "clean-#{Targets[0]}"

# Set target
def set_target(name)
	case name
	when "debug"
		$C_OPT = C_OPT_DBG
		$LIB_FILE = "#{LIB_PATH}/lib#{PROJECT}-dbg.a"

	when "release"
		$C_OPT = C_OPT_REL
		$LIB_FILE = "#{LIB_PATH}/lib#{PROJECT}.a"

	when "profile"
		$C_OPT = C_OPT_PRF
		$LIB_FILE = "#{LIB_PATH}/lib#{PROJECT}-prof.a"

	else
		raise "illegal target: #{name}"
	end


	$TARGET = name
	$OBJ_PATH = "#{OBJ_PATH_BASE}/#{name}"
	$DEPEND = "#{$OBJ_PATH}/depend"
	$OBJS = SRCS.ext(OBJ_EXT).collect {|item| "#{$OBJ_PATH}/#{File.basename(item)}"}

	file $OBJ_PATH do
		sh "mkdir -p #{$OBJ_PATH}"
	end

	file $DEPEND => $OBJ_PATH do
		sh "#{CC} #{INCLUDES} -MM #{SRCS} > #{$DEPEND}"
	end

	file $LIB_FILE => [LIB_PATH] + $OBJS do |t|
		sh "#{AR} #{t.name} #{$OBJS} #{AR_OPT}"
	end

	task "build" => [$OBJ_PATH, $DEPEND, $LIB_FILE]
end

# Load gcc depend file.
def load_depend(fn)
	h = {}
	File.open(fn) do |f|
		while f.gets
			line = $_.chomp
			line = Regexp.last_match.pre_match + f.gets.chomp	while line =~ /\\$/
			h[$1] = $2.split(/\s+/)		if line =~ /^([^:]+):\s*(.*)$/
		end
	end
	return h
end

# find source from target file name
find_depend = lambda do |target_name|
	$depend = load_depend($DEPEND) unless $depend
	$depend[File.basename(target_name)]
end

# rule: obj from src
rule /.#{OBJ_EXT}$/ => find_depend do |t|
	sh "#{CC} #{INCLUDES} #{$C_OPT} -c -o#{t.name} #{t.source}"
end

directory LIB_PATH

desc "Clean all object and library files"
task "clean-all" do
	sh "rm -rf #{OBJ_PATH_BASE}"
	sh "rm -rf #{LIB_PATH}"
end

desc "Clean objects only"
task "clean-objects" do
	sh "rm -rf #{OBJ_PATH_BASE}"
end

def clean_target
	sh "rm -rf #{$OBJ_PATH}"
	sh "rm -rf #{$LIB_FILE}"
end
